/**
 * Copyright (C) 2009 - 2013 SC 4ViewSoft SRL
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.achartengine.chart;

import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;

import org.achartengine.model.Point;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.renderer.support.SupportSeriesRender;

import java.util.List;

/**
 * The interpolated (cubic) line chart rendering class.
 * 会在原有的CubicLine的基础上进行功能的扩展
 */
public class SupportCubicLineChart extends LineChart {
    /**
     * The chart type.
     */
    public static final String TYPE = "Cubic";

    private float firstMultiplier;

    private float secondMultiplier;

    private Point p1 = new Point();

    private Point p2 = new Point();

    private Point p3 = new Point();


    public SupportCubicLineChart() {

        // default is to have first control point at about 33% of the distance,
        firstMultiplier = 0.33f;
        // and the next at 66% of the distance.
        secondMultiplier = 1 - firstMultiplier;
    }

    /**
     * Builds a cubic line chart.
     *
     * @param dataset    the dataset
     * @param renderer   the renderer
     * @param smoothness smoothness determines how smooth the curve should be,
     *                   range [0->0.5] super smooth, 0.5, means that it might not get
     *                   close to control points if you have random data // less smooth,
     *                   (close to 0) means that it will most likely touch all control //
     *                   points
     */
    public SupportCubicLineChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer,
                                 float smoothness) {
        super(dataset, renderer);
        firstMultiplier = smoothness;
        secondMultiplier = 1 - firstMultiplier;
    }

    @Override
    protected void drawPath(Canvas canvas, List<Float> points, Paint paint, boolean circular) {
        Path path = new Path();
        float x = points.get(0);
        float y = points.get(1);
        path.moveTo(x, y);

        int length = points.size();
        if (circular) {
            length -= 4;
        }

        for (int i = 0; i < length; i += 2) {
            int nextIndex = i + 2 < length ? i + 2 : i;
            int nextNextIndex = i + 4 < length ? i + 4 : nextIndex;
            calc(points, p1, i, nextIndex, secondMultiplier);
            p2.setX(points.get(nextIndex));
            p2.setY(points.get(nextIndex + 1));
            calc(points, p3, nextIndex, nextNextIndex, firstMultiplier);
            // From last point, approaching x1/y1 and x2/y2 and ends up at x3/y3
            path.cubicTo(p1.getX(), p1.getY(), p2.getX(), p2.getY(), p3.getX(), p3.getY());
        }
        if (circular) {
            for (int i = length; i < length + 4; i += 2) {
                path.lineTo(points.get(i), points.get(i + 1));
            }
            path.lineTo(points.get(0), points.get(1));
        }

        paint.setAntiAlias(true);
        // 开始为曲线设置颜色，渐变等属性  cvte.wangjia
        if (supportSeriesRender.isSupportShapeLineColor()) {
            paint.setShader(null);
            Shader mShader = new LinearGradient(0, 0, 0, canvas.getHeight(),
                    supportSeriesRender.getShapeLineColor(),
                    new float[]{0.25f, 0.55f, 1.0f}, Shader.TileMode.REPEAT);
            paint.setShader(mShader);

        } else {
            paint.setColor(supportSeriesRender.getLineColor());
        }

        canvas.drawPath(path, paint);
        paint.setShader(null);
    }

    private void calc(List<Float> points, Point result, int index1, int index2, final float multiplier) {
        float p1x = points.get(index1);
        float p1y = points.get(index1 + 1);
        float p2x = points.get(index2);
        float p2y = points.get(index2 + 1);

        float diffX = p2x - p1x; // p2.x - p1.x;
        float diffY = p2y - p1y; // p2.y - p1.y;
        result.setX(p1x + (diffX * multiplier));
        result.setY(p1y + (diffY * multiplier));
    }

    /**
     * Returns the chart type identifier.
     *
     * @return the chart type
     */
    public String getChartType() {
        return TYPE;
    }

}
